home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programmierung
/
Power-Programmierung (Tewi)(1994).iso
/
magazine
/
msysjour
/
vol06
/
02
/
lanman2
/
init.c
next >
Wrap
C/C++ Source or Header
|
1991-02-28
|
15KB
|
404 lines
/*-------------------------------------------------------------------
INIT.C -- PBX initialization related routines
Description:
These various routines are used during PBX initialization to
allocate memory, initialize memory, and to create the child
threads.
Author: Brendan Dixon
Microsoft, inc.
LAN Manager Developer Support
This code example is provided for demonstration purposes only.
Microsoft makes no warranty, either express or implied,
as to its usability in any given situation.
-------------------------------------------------------------------*/
// Includes ---------------------------------------------------------
#define INCL_DOS
#define INCL_DOSERRORS
#include <os2.h>
#define INCL_NETSERVICE
#define INCL_NETWKSTA
#define INCL_NETERRORS
#include <lan.h>
#include <process.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include "pbxsrv.h"
/* AllocatePipeMgrMem -----------------------------------------------
Description: Allocate and initialize memory structures used
by the PipeMgr thread
Input : None
Output : None, globals modified
-------------------------------------------------------------------*/
void AllocatePipeMgrMem(void)
{
USHORT usRetCode; // Return code
// Allocate buffer for PipeMgr thread
usRetCode = DosAllocSeg(pbPBXMem->usLineBufSize, // Size
&(pbPBXMem->selBuf), // Selector
SEG_GETTABLE); // Shared
if (usRetCode) {
ERRRPT("Unable to allocate PipeMgr buffer, DosAllocSeg",
usRetCode, Error);
ulExitCode = SERVICE_UIC_CODE(SERVICE_UIC_RESOURCE,
SERVICE_UIC_M_MEMORY);
ExitHandler();
}
pbPBXMem->pbBuf = MAKEP(pbPBXMem->selBuf, 0);
// Allocate PIPESEMSTATE array (for the PipeMgr thread)
// The maximum number of PIPESEMSTATE records ever returned by
// the DosQNmPipeSemState call (see PIPEMGR.C) is three times the
// number of pipes plus one extra for the NPSS_EOI record.
pbPBXMem->usPSemStateSize = ((3*pbPBXMem->usLines)+1) *
sizeof(PIPESEMSTATE);
usRetCode = DosAllocSeg(pbPBXMem->usPSemStateSize, // Size
&(pbPBXMem->selPSemState), // Selector
SEG_GETTABLE); // Shared
if (usRetCode) {
ERRRPT(
"Unable to allocate PipeMgr PIPESEMSTATE array, DosAllocSeg",
usRetCode, Error);
ulExitCode = SERVICE_UIC_CODE(SERVICE_UIC_RESOURCE,
SERVICE_UIC_M_MEMORY);
ExitHandler();
}
pbPBXMem->aPSemState = MAKEP(pbPBXMem->selPSemState, 0);
return;
}
/* AllocateRouterMem ------------------------------------------------
Description: Allocate and initialize structures used by each
Router thread
Input : None
Output : None, globals modified
-------------------------------------------------------------------*/
void AllocateRouterMem(void)
{
USHORT usPSemStateSize; // PIPESEMSTATE array size
USHORT usRNum; // Structure number
CHAR pszSem[255]; // Semaphore name
USHORT usRetCode; // Return code
// Allocate Router thread structures
usRetCode = DosAllocSeg(
pbPBXMem->usRThreadCnt * sizeof(RTHREAD), // Size
&(pbPBXMem->selRouters), // Selector
SEG_GETTABLE); // Shared
if (usRetCode) {
ERRRPT("Unable to allocate Router structures, DosAllocSeg",
usRetCode, Error);
ulExitCode = SERVICE_UIC_CODE(SERVICE_UIC_RESOURCE,
SERVICE_UIC_M_MEMORY);
ExitHandler();
}
pbPBXMem->abRouters = MAKEP(pbPBXMem->selRouters, 0);
// Determine size of PIPESEMSTATE array for each thread
// Again, allocate space for three records per each pipe (there
// two pipes per connection) plus one extra for the NPSS_CLOSE
// record
usPSemStateSize = ((3*(pbPBXMem->usConnsPerThread*2))+1) *
sizeof(PIPESEMSTATE);
for (usRNum=0; usRNum < pbPBXMem->usRThreadCnt; usRNum++) {
pbPBXMem->abRouters[usRNum].sRouterID = 0;
pbPBXMem->abRouters[usRNum].cConnections = 0;
pbPBXMem->abRouters[usRNum].semRAccess = 0;
// Create the pipe semaphore for the thread
sprintf(pszSem, ROUTERSEM, usRNum);
usRetCode = DosCreateSem(
CSEM_PUBLIC,
&(pbPBXMem->abRouters[usRNum].hsemRouter),
pszSem);
if (usRetCode) {
ERRRPT("DosCreateSem", usRetCode, Error);
ulExitCode = SERVICE_UIC_CODE(SERVICE_UIC_SYSTEM,
usRetCode);
ExitHandler();
}
// Set the Router semaphore to capture the first pipe events
DosSemSet(pbPBXMem->abRouters[usRNum].hsemRouter);
// Allocate line buffer
usRetCode = DosAllocSeg(
pbPBXMem->usLineBufSize, // Size
&(pbPBXMem->abRouters[usRNum].selLineBuf),// Selector
SEG_GETTABLE); // Shared
if (usRetCode) {
ERRRPT("Unable to allocate Router line buffer, DosAllocSeg",
usRetCode, Error);
ulExitCode = SERVICE_UIC_CODE(SERVICE_UIC_RESOURCE,
SERVICE_UIC_M_MEMORY);
ExitHandler();
}
pbPBXMem->abRouters[usRNum].pbLineBuf =
MAKEP(pbPBXMem->abRouters[usRNum].selLineBuf, 0);
// Allocate NPSS_RDATA array
usRetCode = DosAllocSeg(
2*pbPBXMem->usConnsPerThread*sizeof(ROUTEENT),// Size
&(pbPBXMem->abRouters[usRNum].selRData), // Selector
SEG_GETTABLE); // Shared
if (usRetCode) {
ERRRPT(
"Unable to allocate Router NPSS_RDATA array, DosAllocSeg",
usRetCode, Error);
ulExitCode = SERVICE_UIC_CODE(SERVICE_UIC_RESOURCE,
SERVICE_UIC_M_MEMORY);
ExitHandler();
}
pbPBXMem->abRouters[usRNum].aRData =
MAKEP(pbPBXMem->abRouters[usRNum].selRData, 0);
// Allocate NPSS_CLOSE array
usRetCode = DosAllocSeg(
2*pbPBXMem->usConnsPerThread*sizeof(ROUTEENT),// Size
&(pbPBXMem->abRouters[usRNum].selClose), // Selector
SEG_GETTABLE); // Shared
if (usRetCode) {
ERRRPT(
"Unable to allocate Router NPSS_CLOSE array, DosAllocSeg",
usRetCode, Error);
ulExitCode = SERVICE_UIC_CODE(SERVICE_UIC_RESOURCE,
SERVICE_UIC_M_MEMORY);
ExitHandler();
}
pbPBXMem->abRouters[usRNum].aClose =
MAKEP(pbPBXMem->abRouters[usRNum].selClose, 0);
// Allocate PIPESEMSTATE array
usRetCode = DosAllocSeg(
usPSemStateSize, // Size
&(pbPBXMem->abRouters[usRNum].selPSemState),// Selector
SEG_GETTABLE); // Shared
if (usRetCode) {
ERRRPT(
"Unable to allocate Router PIPESEMSTATE array, DosAllocSeg",
usRetCode, Error);
ulExitCode = SERVICE_UIC_CODE(SERVICE_UIC_RESOURCE,
SERVICE_UIC_M_MEMORY);
ExitHandler();
}
pbPBXMem->abRouters[usRNum].aPSemState =
MAKEP(pbPBXMem->abRouters[usRNum].selPSemState, 0);
pbPBXMem->abRouters[usRNum].usPSemStateSize = usPSemStateSize;
}
return;
}
/* AllocateRoutingTable ---------------------------------------------
Description: Build and initialize the PBX routing table
Input : None
Output : None, globals modified
-------------------------------------------------------------------*/
void AllocateRoutingTable(void)
{
USHORT usLineNum; // Current line number
USHORT usRetCode; // Return code
// Allocate Routing Table
usRetCode = DosAllocSeg(
pbPBXMem->usLines * sizeof(ROUTEENT), // Size
&(pbPBXMem->selRTable), // Selector
SEG_GETTABLE); // Shared
if (usRetCode) {
ERRRPT("Unable to allocate routing table, DosAllocSeg",
usRetCode, Error);
ulExitCode = SERVICE_UIC_CODE(SERVICE_UIC_RESOURCE,
SERVICE_UIC_M_MEMORY);
ExitHandler();
}
pbPBXMem->abRTable = MAKEP(pbPBXMem->selRTable, 0);
// Initialize Routing Table
for (usLineNum = 0;
usLineNum < pbPBXMem->usLines;
usLineNum++) {
// Initialize information fields
pbPBXMem->abRTable[usLineNum].pszName[0] = '\0';
pbPBXMem->abRTable[usLineNum].usClientType = 0;
pbPBXMem->abRTable[usLineNum].fState = Available;
pbPBXMem->abRTable[usLineNum].usConnection = usLineNum;
pbPBXMem->abRTable[usLineNum].usWSpace =
pbPBXMem->usLineBufSize;
pbPBXMem->abRTable[usLineNum].usRData = 0;
pbPBXMem->abRTable[usLineNum].hLine = 0;
}
return;
}
/* BuildPBXMsg ------------------------------------------------------
Description: Build an announcement message consisting of the
computer name on which PBX is executing prepended
with two back-slashes (as in a UNC name)
Input : None
Output : None, globals modified
-------------------------------------------------------------------*/
void BuildPBXMsg(void)
{
USHORT usBufSize; // Buffer size in bytes
SEL selBuf; // Buffer selector
struct wksta_info_10 _far *pbWkstaInfo10; // Wksta structure
USHORT usRetCode; // Return code
// Make one call to get the size of buffer required
usRetCode = NetWkstaGetInfo(NULL, // Local
10, // Basic info
NULL, // Get buffer size
0, // No buffer
&usBufSize); // Return size needed
if (usRetCode && usRetCode != NERR_BufTooSmall) {
ERRRPT("NetWkstaGetInfo", usRetCode, Error);
ulExitCode = SERVICE_UIC_CODE(SERVICE_UIC_SYSTEM, usRetCode);
ExitHandler();
}
// Allocate the needed buffer
usRetCode = DosAllocSeg(usBufSize, &selBuf, SEG_NONSHARED);
if (usRetCode) {
ERRRPT("DosAllocSeg", usRetCode, Error);
ulExitCode = SERVICE_UIC_CODE(SERVICE_UIC_RESOURCE,
SERVICE_UIC_M_MEMORY);
ExitHandler();
}
pbWkstaInfo10 = MAKEP(selBuf, 0);
// Get the workstation information
usRetCode = NetWkstaGetInfo(
NULL, // Local
10, // Basic info
(CHAR _far *)pbWkstaInfo10, // Buffer addr
usBufSize, // Buffer size
&usBufSize); // Bytes avail
if (usRetCode) {
ERRRPT("NetWkstaGetInfo", usRetCode, Error);
ulExitCode = SERVICE_UIC_CODE(SERVICE_UIC_SYSTEM, usRetCode);
ExitHandler();
}
// Build announcement message using the current computer name
else {
strcpy(pbPBXMem->pszPBXMsg, "\\\\");
strcat(pbPBXMem->pszPBXMsg,
pbWkstaInfo10->wki10_computername);
pbPBXMem->usPBXMsgSize = strlen(pbPBXMem->pszPBXMsg) + 1;
}
// Free allocated memory
if (usRetCode = DosFreeSeg(selBuf))
ERRRPT("DosFreeSeg", usRetCode, Warning);
return;
}
/* CreateThreads ----------------------------------------------------
Description: Create the MakePipe, PipeMgr, and Router threads
Input : None
Output : None
-------------------------------------------------------------------*/
void CreateThreads(void)
{
CHAR pszMsg[80]; // Error message buffer
USHORT usRetCode; // Return code
// Because pipes are created by the MakePipe thread, transferred
// to the PipeMgr thread, and finally to a Router thread; Router
// threads are created first, then the PipeMgr thread, and finally
// the MakePipe thread. This ensures that all threads will be
// fully ready to handle pipes as they become available.
// Create Router threads
{ USHORT usRNum; // Current Router thread
SHORT sThreadID; // Thread ID
for (usRNum=0; usRNum < pbPBXMem->usRThreadCnt; usRNum++) {
// Create the thread
sThreadID = _beginthread(
(void (_cdecl _far *)(void _far *))Router,
NULL,
ROUTERSTACKSIZE,
(void *)usRNum);
if (sThreadID < 0) {
sprintf(pszMsg, "Unable to start Router thread %u", usRNum);
ERRRPT(pszMsg, 0, Error);
ulExitCode = SERVICE_UIC_CODE(SERVICE_UIC_RESOURCE,
SERVICE_UIC_M_THREADS);
ExitHandler();
}
// Save the thread number
pbPBXMem->abRouters[usRNum].sRouterID = sThreadID;
}
}
// Create the PipeMgr thread
{ SHORT sPipeMgrID;
// Create the pipe semaphore
usRetCode = DosCreateSem(CSEM_PUBLIC,
&(pbPBXMem->hsemPipeMgr),
PIPEMGRSEM);
if (usRetCode) {
ERRRPT("DosCreateSem", usRetCode, Error);
ulExitCode = SERVICE_UIC_CODE(SERVICE_UIC_SYSTEM, usRetCode);
ExitHandler();
}
// Set the semaphore to capture the first pipe events
DosSemSet(pbPBXMem->hsemPipeMgr);
// Create the thread
sPipeMgrID = _beginthread(
(void (_cdecl _far *)(void _far *))PipeMgr,
NULL,
PIPEMGRSTACKSIZE,
NULL);
if (sPipeMgrID < 0) {
ERRRPT("Unable to start PipeMgr thread", 0, Error);
ulExitCode = SERVICE_UIC_CODE(SERVICE_UIC_RESOURCE,
SERVICE_UIC_M_THREADS);
ExitHandler();
}
}
// Create the MakePipe thread
{ SHORT sMakePipeID;
sMakePipeID = _beginthread(
(void (_cdecl _far *)(void _far *))MakePipe,
NULL,
MPIPESTACKSIZE,
NULL);
if (sMakePipeID < 0) {
ERRRPT("Unable to start MakePipe thread", 0, Error);
ulExitCode = SERVICE_UIC_CODE(SERVICE_UIC_RESOURCE,
SERVICE_UIC_M_THREADS);
ExitHandler();
}
}
return;
}